package gsp420.game;

import java.awt.Graphics;

/** @author Michael Vaganov */
public class Board {
	/** grid of tiles */
	Tile[][] board = new Tile[Rules.BOARD_SIZE][Rules.BOARD_SIZE];
	/** all of the tiles in the board */
	Tile[] tiles = new Tile[(Rules.BOARD_SIZE*Rules.BOARD_SIZE)+1];

	void init(){

		// number of each of the different tiles
		int tileCount[] = Rules.TILE_AMOUNT.clone();
		int index = 0;
		// create tiles (un initialized)
		for(int i = 0; i < tiles.length; ++i)
		{
			tiles[i] = new Tile();
			// blank tiles
			tiles[i].init(-1, Rules.BOARD_SIZE, Rules.BOARD_SIZE);
		}
		// set tiles on the board
		for(int y = 0; y < Rules.BOARD_SIZE; ++y)
		{
			for(int x = 0; x < Rules.BOARD_SIZE; ++x){
				// shifted, random tile
				if(Rules.startingRules[y][x][0] == -1){
					// blank tile at the given location
					tiles[index].init(-1, x, y);
				}else{
					// specific tile from the rule set
					int type = Rules.startingRules[y][x][0];
					int rotationCount = Rules.startingRules[y][x][1];
					tiles[index].init(type, x, y);
					tileCount[type]--;
					for(int i = 0; i < rotationCount; ++i)
						tiles[index].rotateCW();
				}
				board[y][x] = tiles[index];
				index++;
			}
		}
		// set all the blank tiles to a random tile from the remaining tiles
		for(int i = 0; i < tiles.length; ++i)
		{
			Tile t = tiles[i];
			// if this is a blank tile
			if(t.type == -1)
			{
				// pick a tile from a random pile
				int type = (int)(Math.random()*tileCount.length);
				while(tileCount[type] == 0){
					type++;
				}
				t.init(type, t.col, t.row);
				tileCount[type]--;
				// rotate it a random number of times
				int rotations = (int)(Math.random()*4);
				for(int r = 0; r < rotations; ++r)
					t.rotateCW();
			}
		}
		ensureCorrectLocationIdentities();
	}
	
	void ensureCorrectLocationIdentities()
	{
		Tile t;
		for(int row = 0; row < board.length; ++row)
		{
			for(int col = 0; col < board[row].length; ++col)
			{
				t = board[row][col];
				t.row = row;
				t.col = col;
			}
		}
	}
	
	/** 
	 * @return the first tile found in the tile list that is not on the map.
	 * @heavyweight 
	 */
	public Tile getUnusedTile()
	{
		Tile t = null;
		for(int i = 0; i < tiles.length; ++i)
		{
			t = tiles[i];
			boolean found = false;
			for(int row = 0; !found && row < board.length; ++row)
			{
				for(int col = 0; !found && col < board[row].length; ++col)
				{
					found = t == board[row][col];
				}
			}
			if(!found)
				return t;
		}
		return t;
	}
	
	void draw(Graphics g, int a_x, int a_y, int a_sqW, int a_sqH)
	{
		for(int row = 0; row < Rules.BOARD_SIZE; ++row)
		{
			for(int col = 0; col < Rules.BOARD_SIZE; ++col)
			{
				board[row][col].draw(g,
					board[row][col].col*Rules.TILE_SIZE*a_sqW+a_x, 
					board[row][col].row*Rules.TILE_SIZE*a_sqH+a_y, 
					a_sqW, a_sqH);
			}
		}
	}
	Tile getTileAt(int x, int y)
	{
		return board[y/Rules.TILE_SIZE][x/Rules.TILE_SIZE];
	}
	char getAt(int x, int y)
	{
		return getTileAt(x,y).map[y%Rules.TILE_SIZE][x%Rules.TILE_SIZE];
	}
}
